#include "Progress.h"
#include "../debug_new.h"

CProgress::CProgress()
{
	Init();
}

CProgress::~CProgress()
{
	m_bmThumb.DeleteObject();
	m_bmThumbActive.DeleteObject();
	m_bmChannel.DeleteObject();
	m_bmChannelActive.DeleteObject();
}

CProgress::CProgress(UINT nID):CControl(nID)
{
	Init();
}

CProgress::CProgress(wstring strCaption,UINT nID)
:	CControl(strCaption,nID)
{
	Init();
}

CProgress::CProgress(DWORD dwStyle,wstring strCaption, const CRect &rc, UINT nID)
:	CControl(dwStyle,strCaption, rc, nID)
{
	Init();
}

CProgress::CProgress(DWORD dwStyle, wstring strCaption, int x, int y, int cx, int cy, UINT nID)
:	CControl(dwStyle, strCaption, x, y, cx, cy, nID)
{
	Init();
}

void CProgress::Init()
{
	m_nPos = m_nMin = 0;
	m_nMax = 100;
	m_nPage = 20;

	m_nMarginLeft = m_nMarginRight = m_nMarginTop = m_nMarginBottom = 0;
	m_nThumbWidth = m_nThumbHeight = 0;

	m_bChannel = m_bVertical = m_bThumb  = FALSE;

	m_clrTransparent = RGB(255,0,255);
}


// Sets the maximum range for the slider.
//
// Parameters:
//		[IN]	nMax
//				Maximum position for the slider.
//		[IN]	bRedraw
//				TRUE to redraw after the range is set.
//				FALSE to only change maximum position.
//
void CProgress::SetRangeMax(int nMax, BOOL bRedraw)
{
	m_nMax = nMax;
	/*if( bRedraw )
		Invalidate();*/
}

// Sets the minimum range for the slider.
//
// Parameters:
//		[IN]	nMin
//				Minimum position for the slider.
//		[IN]	bRedraw
//				TRUE to redraw after the range is set.
//				FALSE to only change minimum position.
//
void CProgress::SetRangeMin(int nMin, BOOL bRedraw)
{
	m_nMin = nMin;
	/*if( bRedraw )
		Invalidate();*/
}

// Sets the range (minimum and maximum positions) for the slider.
//
// Parameters:
//		[IN]	nMin
//				Minimum position for the slider.
//		[IN]	nMax
//				Maximum position for the slider.
//		[IN]	bRedraw
//				TRUE to redraw after the range is set.
//				FALSE to only change the range.
//
void CProgress::SetRange(int nMin, int nMax, BOOL bRedraw)
{
	SetRangeMin( nMin, FALSE );
	SetRangeMax( nMax, bRedraw );
}

// Sets the current position of the slider.
//
// Parameters:
//		[IN]	nPos
//				Specifies the new slider position.
//
void CProgress::SetPos(int nPos)
{
	m_nPos = nPos;

	// Boundary check
	if( m_nPos >= m_nMax )
	{
		m_nPos = m_nMax;
	}
	if( m_nPos <= m_nMin )
	{
		m_nPos = m_nMin;
	}

	//Invalidate();
	//UpdateWindow();
}

// Sets the size of the page for a control.
//
// Parameters:
//		[IN]	nSize
//				The new page size of the control.
//
// Return value:
//		The previous page size.
//
int CProgress::SetPageSize(int nSize)
{
	int nRet = m_nPage;

	m_nPage = nSize;

	return nRet;
}

// Sets the left, top, right, and bottom margins for a control
//
void CProgress::SetMargin(int nLeft, int nTop, int nRight, int nBottom )
{
	SetMarginLeft( nLeft );
	SetMarginTop( nTop );
	SetMarginRight( nRight );
	SetMarginBottom( nBottom );
}


// Specify whether draw focus rectangle or not.
//
//		[IN]	bDraw
//				TRUE to draw focus rectangle.
//				FALSE to hide focus rectangle.
//
//		[IN]	bRedraw
//				TRUE to redraw status is changed.
//				FALSE to only change the status.
//
void CProgress::DrawFocusRect(BOOL bDraw, BOOL bRedraw)
{

}

// Load bitmaps for a channel
//
// Parameters:
//		[IN]	nChannelID
//				ID number of the bitmap resource of the channel.
//		[IN]	nActiveID
//				ID number of the bitmap resource of the active channel.
//		[IN]	bTransparent
//				TRUE to apply transparency effect.
//				FALSE to display normal bitmap.
//		[IN]	clrpTransColor
//				RGB color to treat as transparent.
//		[IN]	iTransPixelX
//				Logical x-coordinate of a point.
//				It's color will be treated as transparent.
//		[IN]	iTransPixelY
//				Logical y-coordinate of a point.
//				It's color will be treated as transparent.
//
// Return value:
//		TRUE
//			Function succeedes.
//		FALSE
//			Function failes to load bitmaps.
//
BOOL CProgress::SetBitmapChannel(HBITMAP hChannel, HBITMAP hActive, BOOL bTransparent,COLORREF clrpTransColor)
{
	// This control will not have any bitmap for channel
	if( NULL == hChannel )
	{
		m_bChannel = FALSE;
		m_bmChannel.DeleteObject();
		m_bmChannelActive.DeleteObject();
		return TRUE;
	}

	// load a bitmap
	m_bmChannel.Attach(hChannel);

	// Load a bitmap for active state.
	if( NULL !=  hActive) 
	{
		m_bmChannelActive.Attach( hActive );
		m_bChannelActive = TRUE;
	}
	else
	{
		m_bChannelActive = FALSE;
	}

	// Get size of bitmap.
	BITMAP	bitmap;
	m_bmChannel.GetBitmap(&bitmap);

	m_nWidth = bitmap.bmWidth;
	m_nHeight = bitmap.bmHeight;

	// Compare size
	if( m_bChannelActive )
	{
		BITMAP	bitmap;
		m_bmChannelActive.GetBitmap( &bitmap );
	}

	m_bTransparentChannel = bTransparent;
	m_bChannel = TRUE;

	m_clrTransparent = clrpTransColor;

	return TRUE;
}

// Load bitmaps for a thumb
//
// Parameters:
//		[IN]	nThumbID
//				ID number of the bitmap resource of the thumb
//		[IN]	nActiveID
//				ID number of the bitmap resource of the active thumb
//		[IN]	bTransparent
//				TRUE to apply transparency effect
//				FALSE to display normal bitmap
//		[IN]	clrpTransColor
//				RGB color to treat as transparent
//		[IN]	iTransPixelX
//				Logical x-coordinate of a point.
//				It's color will be treated as transparent
//		[IN]	iTransPixelY
//				Logical y-coordinate of a point.
//				It's color will be treated as transparent
//
// Return value:
//		TRUE
//			Function succeedes.
//		FALSE
//			Function failes to load bitmaps.
//
BOOL CProgress::SetBitmapThumb(
								HBITMAP hThumb, HBITMAP hActive, BOOL bTransparent,
								COLORREF clrpTransColor)
{
	// This control will not have bitmap
	if(NULL == hThumb)
	{
		m_bThumb = FALSE;
		m_bmThumb.DeleteObject();
		m_bmThumbActive.DeleteObject();
		return TRUE;
	}

	m_bmThumb.Attach(hThumb);
	// Load a bitmap for active state.
	if( NULL != hActive )
	{
		m_bmThumbActive.Attach( hActive );
		m_bThumbActive = TRUE;
	} 
	else
	{
		m_bThumbActive = FALSE;
	}

	// Get size of the bitmap
	BITMAP	bitmap;
	m_bmThumb.GetBitmap( &bitmap );

	m_nThumbWidth = bitmap.bmWidth;
	m_nThumbHeight = bitmap.bmHeight;

	// Compare size
	if( m_bThumbActive )
	{
		BITMAP	bitmap;
		m_bmThumbActive.GetBitmap( &bitmap );
	}

	// Set attributes
	m_bTransparentChannel = bTransparent;
	m_bThumb = TRUE;
	m_clrTransparent = clrpTransColor;

	return TRUE;
}

// Calculate point of thumb from position value
//
int CProgress::Pos2Pixel(int nPos)
{
	if( m_bVertical )
	{
		return
			m_nMarginTop + m_nThumbHeight/2 +
			(int)(
			( m_nHeight - m_nMarginTop - m_nMarginBottom - m_nThumbHeight ) *
			((double) ( nPos - m_nMin ) / ( m_nMax - m_nMin ) )
			);

	} else
	{
		return (int)(
			( m_nWidth - m_nMarginLeft - m_nMarginRight - m_nThumbWidth ) *
			((double) ( nPos - m_nMin ) / ( m_nMax - m_nMin ) )
			) + m_nMarginLeft + m_nThumbWidth/2;
	}
}

// Calculate position value from point of mouse
//
int CProgress::Pixel2Pos(int nPixel)
{
#if 1
	if( m_bVertical )
	{
		double fltpos = (  (double)m_nMin +
			(double)( nPixel - m_nMarginTop - m_nThumbHeight/2) /
			( m_nHeight - m_nMarginBottom - m_nMarginTop - m_nThumbHeight ) *
			( m_nMax - m_nMin )
			);
		int nPos = fltpos;  
		if ( (fltpos-(double)nPos)>=0.6 )
		{
			nPos += 1;
		}
		return nPos;

	}
	else
	{

		double fltpos = (  (double)m_nMin +
			(double)( nPixel - m_nMarginLeft - m_nThumbWidth/2 ) /
			( m_nWidth - m_nMarginLeft - m_nMarginRight - m_nThumbWidth ) *
			( m_nMax - m_nMin )
			);
		int nPos = fltpos;  
		if ( (fltpos-(double)nPos)>=0.6 )
		{
			nPos += 1;
		}
		return nPos;
	}
#else
	if( m_bVertical )
	{
		return (int)(
			m_nMin +
			(double)( nPixel - m_nMarginTop - m_nThumbHeight/2) /
			( m_nHeight - m_nMarginBottom - m_nMarginTop - m_nThumbHeight ) *
			( m_nMax - m_nMin )
			);
	}
	else
	{
		return (int)(
			m_nMin +
			(double)( nPixel - m_nMarginLeft - m_nThumbWidth/2 ) /
			( m_nWidth - m_nMarginLeft - m_nMarginRight - m_nThumbWidth ) *
			( m_nMax - m_nMin )
			);
	}

#endif

}

void CProgress::DrawBitmap(CDC *pDC, int xStart, int yStart, int wWidth, int wHeight,CDC *pTmpDC, int xSource, int ySource)
{
	if( m_bTransparentChannel ) 
	{
		pDC->TransparentBltEx(xStart,yStart,wWidth,wHeight,pTmpDC->m_hDC,xSource,ySource,wWidth,wHeight,m_clrTransparent);
	} 
	else 
	{
		pDC->BitBlt( xStart, yStart,
			wWidth, wHeight,
			pTmpDC->m_hDC, xSource, ySource, SRCCOPY );
	}
}

void CProgress::Paint(CDC* pDC)
{
	if(m_rcControl.IsRectEmpty())
	{
		return ;
	}

	if(!IsVisible())
	{
		return;
	}

	//PaintBackGnd(pDC); //leon comment for progress flicking 09-05-12

	CDC dcMem;
	dcMem.CreateCompatibleDC(pDC->m_hDC);

	HBITMAP pbmTmp;
	// Draw channel
	if( m_bChannel ) 
	{
		pbmTmp = dcMem.SelectBitmap( m_bmChannel.m_hBitmap );
		// There is a bitmap for active channel
		if( m_bChannelActive) 
		{
			// Vertical slider
			if( m_bVertical ) 
			{
				// Lower part
				DrawBitmap( pDC, m_rcControl.left, m_rcControl.top+Pos2Pixel(m_nPos),
					m_nWidth, m_nHeight - Pos2Pixel(m_nPos),
					&dcMem, 0, Pos2Pixel(m_nPos)
					);

				dcMem.SelectBitmap(m_bmChannelActive.m_hBitmap);
				// Upper part
				DrawBitmap(pDC,m_rcControl.left,m_rcControl.top,m_nWidth,Pos2Pixel(m_nPos),&dcMem, 0, 0);
			}
			else // Horizontal slider
			{
				// Right side
				DrawBitmap(pDC, m_rcControl.left+Pos2Pixel(m_nPos),m_rcControl.top,
					m_nWidth - Pos2Pixel(m_nPos), m_nHeight,
					&dcMem, Pos2Pixel(m_nPos), 0
					);

				dcMem.SelectBitmap( m_bmChannelActive.m_hBitmap );
				// Left side
				DrawBitmap(pDC, m_rcControl.left, m_rcControl.top, Pos2Pixel(m_nPos), m_nHeight,&dcMem, 0, 0);
			}

			// Only one bitmap for channel
		}
		else
		{
			DrawBitmap(pDC, m_rcControl.left, m_rcControl.top, m_nWidth, m_nHeight,	&dcMem, 0, 0);
		}

		dcMem.SelectBitmap( pbmTmp );
	}

	// Draw thumb
	if( m_bThumb)
	{
		if( m_bThumbActive && (m_nState & STATE_PUSHED))
			pbmTmp = dcMem.SelectBitmap(m_bmThumbActive.m_hBitmap); // Active thumb
		else
			pbmTmp = dcMem.SelectBitmap(m_bmThumb.m_hBitmap); // Normal thumb

		// Vertical slider
		if( m_bVertical )
		{
			DrawBitmap(
				pDC, m_rcControl.left+m_nMarginLeft, m_rcControl.top+Pos2Pixel(m_nPos) - m_nThumbHeight/2,
				m_nThumbWidth, m_nThumbHeight,
				&dcMem, 0, 0);
		} 
		else // Horizontal slider
		{
			DrawBitmap(
				pDC, m_rcControl.left+Pos2Pixel(m_nPos) - m_nThumbWidth/2, m_rcControl.top+m_nMarginTop,
				m_nThumbWidth, m_nThumbHeight,
				&dcMem, 0, 0);

		} // if horizontal

		dcMem.SelectBitmap( pbmTmp );

	} // if draw thumb

	dcMem.DeleteDC();
}

void CProgress::Click(DWORD dwClick, POINT point)
{
	BOOL bSendMsg = FALSE;
	if(!IsEnabled())
	{
		return;
	}

	if(!m_bVisibale)
	{
		return;
	}

	if(!m_pContainer || !m_pContainer->m_hWnd)
	{
		return;
	}

	if(!m_rcControl.PtInRect(point))
	{ 
		m_nState = STATE_NORMAL;
		return;
	}
	else
	{
		if(dwClick & CLICK_DOWN)
		{			
			m_nState = STATE_PUSHED;
			bSendMsg = TRUE;
		}
		else if(dwClick & CLICK_UP)
		{
			if(m_pContainer->m_hWnd)
				//PostMessage(m_pContainer->m_hWnd,WM_COMMAND, m_nID,NULL);
				bSendMsg = TRUE;
			m_nState = STATE_NORMAL;
		}
	}

	point.x -= m_rcControl.left;
	point.y -= m_rcControl.top;

/////////////////////////////////////////////////////

	if( m_bVertical ) 
	{
		if( abs( point.y - Pos2Pixel( m_nPos ) ) <= m_nThumbHeight / 2 )
			m_nMouseOffset = point.y - Pos2Pixel( m_nPos );
		else
			m_nMouseOffset = 0;
	}
	else
	{
		if( abs( point.x - Pos2Pixel( m_nPos ) ) <= m_nThumbWidth / 2 )
			m_nMouseOffset = point.x - Pos2Pixel( m_nPos );
		else
			m_nMouseOffset = 0;
	}

/////////////////////////////////////

	int nPixel;

	// Boundary check
	if( m_bVertical )
	{
		nPixel = point.y - m_nMouseOffset;

		if( nPixel > m_nHeight - m_nMarginBottom - m_nThumbHeight/2 )
			nPixel = m_nHeight - m_nMarginBottom - m_nThumbHeight/2;

		if( nPixel < m_nMarginTop + m_nThumbHeight/2 )
			nPixel = m_nMarginTop + m_nThumbHeight/2;

	} 
	else
	{
		nPixel = point.x - m_nMouseOffset;

		if( nPixel < m_nMarginLeft + m_nThumbWidth/2 )
			nPixel = m_nMarginLeft + m_nThumbWidth/2;

		if( nPixel > m_nWidth - m_nMarginRight - m_nThumbWidth/2 )
			nPixel = m_nWidth - m_nMarginRight - m_nThumbWidth/2;
	}

	// Apply change
	if( Pos2Pixel(m_nPos) != nPixel )
	{
		SetPos( Pixel2Pos( nPixel ) );
	}

	if(bSendMsg)
	{
		PostMessage(m_pContainer->m_hWnd,WM_COMMAND, m_nID,NULL);
	}
}